using System;
using LoggingMagic.Injectors;
using LoggingMagic.Injectors.StaticField.Base;
using LoggingMagic.Injectors.StaticField.Parameters;
using LoggingMagic.Injectors.StaticField.StaticFieldWithMethodName;
using LoggingMagic.Injectors.StaticMethod;
using LoggingMagic.LoggingParameters;
using Mono.Cecil;

namespace LoggingMagic
{
    internal class Resolver
    {
        public InjectorFactory CreateFactory(ModuleDefinition module, IAssemblyResolver resolver, ILoggingTaskAttributes attributes)
        {
            var injectorType = GetInjectorType(attributes.Injector);
            var methodFinderParameters = new MethodFinderParameters(attributes);

            switch (injectorType)
            {
                case InjectorType.StaticMethodCall:
                    return new StaticMethodFactory(module, resolver, methodFinderParameters);


                case InjectorType.StaticFieldMethodCall:
                    return new StaticFieldFactory(module, resolver, methodFinderParameters, GetStaticFieldParameters(attributes));


                case InjectorType.StaticFieldMethodCallWithMethodName:
                    return new StaticFieldWithMethodNameFactory(module, resolver, methodFinderParameters, GetStaticFieldParameters(attributes));

                default:
                    throw new NotImplementedException(String.Format("factory for injector {0} is not implemented", injectorType));
            }
        }

        private IStaticFieldParameters GetStaticFieldParameters(ILoggingTaskAttributes attributes)
        {
            StaticFieldParameters injectorParameters;
            switch (attributes.Parameters.ToLower())
            {
                case "log4net":
                    injectorParameters = new Log4NetParameters(attributes);
                    break;

                case "log4netinfo":
                    injectorParameters = new Log4NetInfoParameters(attributes);
                    break;

                case "nlog":
                    injectorParameters = new NLogParameters(attributes);
                    break;

                case "message":
                    injectorParameters = new MessageParameters(attributes);
                    break;

                default:
                    throw new NotImplementedException(String.Format("Wrong parameters type {0} for injector {1}", attributes.Parameters, attributes.Injector));
            }

            return injectorParameters;
        }

        private InjectorType GetInjectorType(string injector)
        {
            InjectorType result;
            if (!Enum.TryParse(injector, true, out result))
            {
                throw new ArgumentException("proper Injector not found");
            }

            return result;
        }

    }
}